home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
usenet
/
sources
/
volume2
/
unix
/
shell211.1
< prev
next >
Wrap
Text File
|
1988-10-25
|
60KB
|
2,608 lines
Path: xanth!nic.MR.NET!tank!mimsy!dftsrv!ames!mailrus!ulowell!page
From: page@swan.ulowell.edu (Bob Page)
Newsgroups: comp.sources.amiga
Subject: v02i022: shell - cshell-like command processor V2.11, Part01/02
Message-ID: <9830@swan.ulowell.edu>
Date: 25 Oct 88 01:46:07 GMT
Organization: University of Lowell, Computer Science Dept.
Lines: 2597
Approved: page@swan.ulowell.edu
Submitted-by: dillon@cory.berkeley.edu (Matt Dillon)
Posting-number: Volume 2, Issue 22
Archive-name: unix/shell211.1
# This is a shell archive. Remove anything before this line
# then unpack it by saving it in a file and typing "sh file"
# (Files unpacked will be owned by you and have default permissions).
# This archive contains the following files:
# examples.txt
# execom.c
# fexec1.c
# fexec2.asm
# globals.c
# hat.c
# main.c
# run.c
# set.c
# shell.h
# sort.c
# sub.c
# tags
#
if `test ! -s examples.txt`
then
echo "writing examples.txt"
cat > examples.txt << '\Rogue\Monster\'
EXAMPLE FILES
------------------------------------------------------------------------
EXAMPLE INTERNAL COMMAND OVERIDING
------------------------------------------------------------------------
#Make CD not only do it's normal function, but also a PWD.
alias cd "%var \\cd $var;pwd"
------------------------------------------------------------------------
.LOGIN
------------------------------------------------------------------------
echo "shells, Matt"
alias l "%var if $var;echo $var;else;echo *;endif"
alias c "echo ^l"
alias cc "cd ram:;assign c: cb:c"
alias wb "cd ram:;assign c: sys:c"
alias ed "run ED"
set dest ram:a
set temp ram:
set ld cb:clib
set incdir cb:include
set libs +$ld/lc.lib
set ops ""
------------------------------------------------------------------------
RAM.SH
------------------------------------------------------------------------
cp c:run ram:; cp c:assign ram:; cp c:cp ram:; assign c: ram:
------------------------------------------------------------------------
C1.SH
------------------------------------------------------------------------
foreach y ( $_passed ) "echo $y;lc1 -o$temp -i$incdir/ -i$incdir/lattice/ $y";echo DONE
------------------------------------------------------------------------
C2.SH
------------------------------------------------------------------------
foreach y ( $_passed ) "echo $y;lc2 -s -v $temp$y";echo DONE
------------------------------------------------------------------------
LD.SH
------------------------------------------------------------------------
blink $ld/lstartup.obj+$_passed library $ld/lc.lib+$ld/amiga.lib $ops to $dest
------------------------------------------------------------------------
LDALL.SH
------------------------------------------------------------------------
set O "";foreach y ( *.o ) "set O $O+$y";strtail O + $O
ld $O;unset O
\Rogue\Monster\
else
echo "will not over write examples.txt"
fi
if [ `wc -c examples.txt | awk '{printf $1}'` -ne 1870 ]
then
echo `wc -c examples.txt | awk '{print "Got " $1 ", Expected " 1870}'`
fi
if `test ! -s execom.c`
then
echo "writing execom.c"
cat > execom.c << '\Rogue\Monster\'
/*
* EXECOM.C
*
* (c)1986 Matthew Dillon 9 October 1986
*
* Handles command parsing.
*
*
*/
#include "shell.h"
#define ST_COND 0x01
#define ST_NAME 0x02
#define ST_EXA 0x04 /* exact match required */
struct COMMAND {
int (*func)();
short minargs;
short stat;
int val;
char *name;
};
extern char *format_insert_string();
extern char *mpush(), *exarg();
extern int do_run(), do_number();
extern int do_quit(), do_set_var(), do_unset_var(), do_setenv(), do_unsetenv();
extern int do_printenv(), do_echo(), do_source(), do_mv();
extern int do_cd(), do_rm(), do_mkdir(), do_history();
extern int do_mem(), do_cat(), do_dir();
extern int do_foreach(), do_return(), do_if(), do_label(), do_goto();
extern int do_forever(), do_inc(), do_abortline();
extern int do_input(), do_ver(), do_sleep(), do_help();
extern int do_strhead(), do_strtail(), do_cp();
extern int do_comment(), do_shellstat(), do_ipc(), do_cldres();
static struct COMMAND Command[] = {
do_run , 0, ST_NAME, 0 , "\001",
do_number , 0, 0, 0 , "\001",
do_quit , 0, ST_EXA, 0 , "quit",
do_quit , 0, ST_EXA, 0 , "exit",
do_set_var , 0, 0, LEVEL_SET , "set",
do_unset_var, 0, 0, LEVEL_SET , "unset",
do_setenv , 2, 0, 0 , "setenv",
do_unsetenv , 0, 0, 0 , "unsetenv",
do_printenv , 0, 0, 0 , "printenv",
do_set_var , 0, 0, LEVEL_ALIAS, "alias",
do_unset_var, 0, 0, LEVEL_ALIAS, "unalias",
do_echo , 0, 0, 0 , "echo",
do_source , 0, 0, 0 , "source",
do_mv , 2, ST_EXA, 0 , "mv",
do_cd , 0, 0, 0 , "cd",
do_cd , 0, 0, -1 , "pwd",
do_rm , 0, ST_EXA, 0 , "rm",
do_mkdir , 0, ST_EXA, 0 , "mkdir",
do_history , 0, 0, 0 , "history",
do_mem , 0, 0, 0 , "mem",
do_cat , 0, 0, 0 , "cat",
do_cp , 1, ST_EXA, 0 , "cp",
do_dir , 0, 0, 0 , "dir",
do_dir , 0, 0, -1 , "devinfo",
do_foreach , 3, 0, 0 , "foreach",
do_forever , 1, 0, 0 , "forever",
do_return , 0, ST_EXA, 0 , "return",
do_ipc , 1, 0, 0 , "ipc",
do_cldres , 0, 0, 0 , "cldres",
do_if , 1, ST_COND, 0 , "if",
do_if , 0, ST_COND, 1 , "else",
do_if , 0, ST_COND, 2 , "endif",
do_label , 1, ST_COND, 0 , "label",
do_goto , 1, 0, 0 , "goto",
do_strhead , 3, 0, 0 , "strhead",
do_strtail , 3, 0, 0 , "strtail",
do_inc , 1, 0, 1 , "inc",
do_inc , 1, 0, -1, "dec",
do_input , 1, 0, 0, "input",
do_ver , 0, 0, 0, "version",
do_sleep , 0, 0, 0, "sleep",
do_help , 0, 0, 0, "help",
do_abortline, 0, 0, 0, "abortline",
do_comment , 2, 0, 0, "comment",
do_shellstat, 0, 0, 0, "shellstat",
NULL , 0, 0, 0 , NULL
};
static unsigned char elast; /* last end delimeter */
static char Cin_ispipe, Cout_ispipe;
exec_command(base)
char *base;
{
register char *scr;
register int i;
char buf[32];
if (!H_stack) {
add_history(base);
sprintf(buf, "%ld", H_tail_base + H_len);
set_var(LEVEL_SET, V_HISTNUM, buf);
}
scr = malloc((strlen(base) << 2) + 2); /* 4X */
preformat(base, scr);
i = fcomm(scr, 1);
return ((i) ? -1 : 1);
}
isalphanum(c)
char c;
{
if (c >= '0' && c <= '9')
return (1);
if (c >= 'a' && c <= 'z')
return (1);
if (c >= 'A' && c <= 'Z')
return (1);
if (c == '_')
return (1);
return (0);
}
preformat(s, d)
register char *s, *d;
{
register short si, di, qm;
si = di = qm = 0;
while (s[si] == ' ' || s[si] == 9)
++si;
while (s[si]) {
if (qm && s[si] != '\"' && s[si] != '\\') {
d[di++] = s[si++] | 0x80;
continue;
}
switch (s[si]) {
case ' ':
case 9:
d[di++] = ' ';
while (s[si] == ' ' || s[si] == 9)
++si;
if (s[si] == 0 || s[si] == '|' || s[si] == ';')
--di;
break;
case '*':
case '?':
d[di++] = 0x80; /* follow thru */
case '!':
d[di++] = s[si++];
break;
case '#':
d[di++] = '\0';
while (s[si])
++si;
break;
case ';':
case '|':
d[di++] = s[si++];
while (s[si] == ' ' || s[si] == 9)
++si;
break;
case '\\':
d[di++] = s[++si] | 0x80;
if (s[si]) ++si;
break;
case '\"':
qm = 1 - qm;
++si;
break;
case '^':
d[di++] = s[++si] & 0x1F;
if (s[si]) ++si;
break;
case '$': /* search end of var name and place false space */
d[di++] = 0x80;
d[di++] = s[si++];
while (isalphanum(s[si]))
d[di++] = s[si++];
d[di++] = 0x80;
break;
default:
d[di++] = s[si++];
break;
}
}
d[di++] = 0;
d[di] = 0;
#ifdef DEBUG
if (SDebug & 0x01) {
fhprintf (Cerr, "PREFORMAT: %ld :%s:\n", strlen(d), d);
}
#endif
}
/*
* process formatted string. ' ' is the delimeter.
*
* 0: check '\0': no more, stop, done.
* 1: check $. if so, extract, format, insert
* 2: check alias. if so, extract, format, insert. goto 1
* 3: check history or substitution, extract, format, insert. goto 1
*
* 4: assume first element now internal or disk based command.
*
* 5: extract each ' ' or 0x80 delimited argument and process, placing
* in av[] list (except 0x80 args appended). check in order:
*
* '$' insert string straight
* '>' setup stdout
* '>>' setup stdout flag for append
* '<' setup stdin
* '*' or '?' do directory search and insert as separate args.
*
* ';' 0 '|' end of command. if '|' setup stdout
* -execute command, fix stdin and out (|) sets
* up stdin for next guy.
*/
fcomm(str, freeok)
register char *str;
{
static short alias_count;
char *istr;
char *nextstr;
char *command;
char *pend_alias = NULL;
char err = 0;
++alias_count;
mpush_base();
if (*str == 0)
goto done1;
step1:
if (alias_count == MAXALIAS) {
Eputs("Alias Loop");
err = 20;
goto done1;
}
if (*str == '$') {
if (istr = get_var (LEVEL_SET, str + 1))
str = format_insert_string(str, istr, &freeok);
}
istr = NULL;
if (*(unsigned char *)str < 0x80)
istr = get_var (LEVEL_ALIAS, str); /* only if not \command */
*str &= 0x7F; /* remove \ teltail */
if (istr) {
if (*istr == '%') {
pend_alias = istr;
} else {
str = format_insert_string(str, istr, &freeok);
goto step1;
}
}
if (*str == '!') {
istr = get_history(str);
replace_head(istr);
str = format_insert_string(str, istr, &freeok);
goto step1;
}
nextstr = str;
command = exarg(&nextstr);
if (*command == 0)
goto done0;
if (pend_alias == 0) {
register int ccno;
ccno = find_command(command);
if (Command[ccno].stat & ST_COND)
goto skipgood;
}
if (SDisable) {
while (elast && elast != ';' && elast != '|')
exarg(&nextstr);
goto done0;
}
skipgood:
{
register char *arg, *ptr, *scr;
short redir;
short doexpand;
short cont;
short inc;
ac = 1;
av[0] = command;
step5: /* ac = nextac */
if (!elast || elast == ';' || elast == '|')
goto stepdone;
av[ac] = NULL;
cont = 1;
doexpand = redir = inc = 0;
while (cont && elast) {
ptr = exarg(&nextstr);
inc = 1;
arg = "";
cont = (elast == 0x80);
switch (*ptr) {
case '<':
redir = -2; /* -2 so ++ still keeps it negative */
case '>':
++redir; /* normal > */
arg = ptr + 1;
if (*arg == '>') {
redir = 2; /* append >> (not impl yet) */
++arg;
}
cont = 1;
break;
case '$':
if ((arg = get_var(LEVEL_SET, ptr + 1)) == NULL)
arg = ptr;
break;
case '*':
case '?':
doexpand = 1;
arg = ptr;
break;
default:
arg = ptr;
break;
}
/* Append arg to av[ac] */
for (scr = arg; *scr; ++scr)
*scr &= 0x7F;
if (av[ac]) {
register char *old = av[ac];
av[ac] = mpush(strlen(arg)+1+strlen(av[ac]));
strcpy(av[ac], old);
strcat(av[ac], arg);
} else {
av[ac] = mpush(strlen(arg)+1);
strcpy(av[ac], arg);
}
if (elast != 0x80)
break;
}
/* process expansion */
if (doexpand) {
char **eav, **ebase;
int eac;
eav = ebase = expand(av[ac], &eac);
inc = 0;
if (eav) {
if (ac + eac + 2 > MAXAV) {
ierror (NULL, 506);
err = 1;
} else {
QuickSort(eav, eac);
for (; eac; --eac, ++eav)
av[ac++] = strcpy(mpush(strlen(*eav)+1), *eav);
}
free_expand (ebase);
}
}
/* process redirection */
if (redir && !err) {
register char *file = (doexpand) ? av[--ac] : av[ac];
if (redir < 0) {
Cin_name = file;
} else {
Cout_name = file;
Cout_append = (redir == 2);
}
inc = 0;
}
/* check elast for space */
if (inc) {
++ac;
if (ac + 2 > MAXAV) {
ierror (NULL, 506);
err = 1; /* error condition */
elast = 0; /* don't process any more arguemnts */
}
}
if (elast == ' ')
goto step5;
}
stepdone:
av[ac] = NULL;
/* process pipes via files */
if (elast == '|' && !err) {
static int which; /* 0 or 1 in case of multiple pipes */
which = 1 - which;
Cout_name = (which) ? Pipe1 : Pipe2;
Cout_ispipe = 1;
}
if (err)
goto done0;
{
register long i, len;
char save_elast;
register char *avline;
save_elast = elast;
for (i = len = 0; i < ac; ++i)
len += strlen(av[i]) + 1;
avline = malloc(len+2);
for (len = 0, i = ((pend_alias) ? 1 : 0); i < ac; ++i) {
#ifdef DEBUG
if (SDebug & 0x02) fhprintf (Cerr, "AV[%2ld] %ld :%s:\n", i, strlen(av[i]), av[i]);
#endif
strcpy(avline + len, av[i]);
len += strlen(av[i]);
if (i + 1 < ac)
avline[len++] = ' ';
}
avline[len] = 0;
if (pend_alias) { /* special % alias */
register char *ptr, *scr;
for (ptr = pend_alias; *ptr && *ptr != ' '; ++ptr);
set_var (LEVEL_SET, pend_alias + 1, avline);
free (avline);
scr = malloc((strlen(ptr) << 2) + 2);
preformat (ptr, scr);
fcomm (scr, 1);
unset_var (LEVEL_SET, pend_alias + 1);
} else { /* normal command */
register short ccno;
register long cin, cout;
ccno = find_command (command);
if ((Command[ccno].stat & ST_NAME) == 0) {
if (Cin_name) {
cin = Cin;
Cin = Open(Cin_name, 1005);
if (Cin == 0) {
ierror (NULL, 504);
err = 1;
Cin = cin;
Cin_name = NULL;
}
}
if (Cout_name) {
cout = Cout;
if (Cout_append) {
if (Cout = Open(Cout_name, 1005))
Seek(Cout, 0, 1);
} else {
Cout = Open(Cout_name, 1006);
}
if (Cout == NULL) {
err = 1;
ierror (NULL, 504);
Cout = cout;
Cout_name = NULL;
Cout_append = 0;
}
}
}
if (ac < Command[ccno].minargs + 1) {
ierror (NULL, 500);
err = -1;
} else {
i = (*Command[ccno].func)(avline, Command[ccno].val);
if (i < 0)
i = 20;
err = i;
}
free (avline);
if (Exec_ignoreresult == 0 && Lastresult != err) {
Lastresult = err;
seterr();
}
if ((Command[ccno].stat & ST_NAME) == 0) {
if (Cin_name) {
Close(Cin);
Cin = cin;
}
if (Cout_name) {
Close(Cout);
Cout = cout;
Cout_append = 0;
}
}
}
if (Cin_ispipe && Cin_name)
DeleteFile(Cin_name);
if (Cout_ispipe) {
Cin_name = Cout_name; /* ok to assign.. static name */
Cin_ispipe = 1;
} else {
Cin_name = NULL;
}
Cout_name = NULL;
Cout_ispipe = Cout_append = 0;
elast = save_elast;
}
mpop_tobase(); /* free arguments */
mpush_base(); /* push dummy base */
done0:
{
register char *str;
#ifdef DEBUG
if (SDebug & 0x10)
printf ("err = %ld, E_stack = %ld\n", err, E_stack);
#endif
if (err && E_stack == 0) {
str = get_var(LEVEL_SET, V_EXCEPT);
if (err >= ((str)?atoi(str):1)) {
if (str) {
++H_stack;
++E_stack;
exec_command(str);
--E_stack;
--H_stack;
} else {
Exec_abortline = 1;
}
}
}
#ifdef DEBUG
if (SDebug & 0x10) {
printf ("elast = %ld Exec_abortline = %ld\n", elast, Exec_abortline);
printf ("nextstr = %s\n", nextstr);
}
#endif
if (elast != 0 && Exec_abortline == 0)
err = fcomm(nextstr, 0);
Exec_abortline = 0;
if (Cin_name)
DeleteFile(Cin_name);
Cin_name = NULL;
Cin_ispipe = 0;
}
done1:
mpop_tobase();
if (freeok)
free(str);
--alias_count;
return ((int)err); /* TRUE = error occured */
}
char *
exarg(ptr)
unsigned char **ptr;
{
register unsigned char *end;
register unsigned char *start;
start = end = *ptr;
while (*end && *end != 0x80 && *end != ';' && *end != '|' && *end != ' ')
++end;
elast = *end;
*end = '\0';
*ptr = end + 1;
return ((char *)start);
}
static char **Mlist;
mpush_base()
{
register char *str;
str = malloc(5);
*(char ***)str = Mlist;
str[4] = 0;
Mlist = (char **)str;
}
char *
mpush(bytes)
{
register char *str;
str = malloc(5 + bytes);
*(char ***)str = Mlist;
str[4] = 1;
Mlist = (char **)str;
return (str + 5);
}
mpop_tobase()
{
register char *next;
while (Mlist) {
next = *Mlist;
if (((char *)Mlist)[4] == 0) {
free (Mlist);
Mlist = (char **)next;
break;
}
free (Mlist);
Mlist = (char **)next;
}
}
/*
* Insert 'from' string in front of 'str' while deleting the
* first entry in 'str'. if freeok is set, then 'str' will be
* free'd
*/
char *
format_insert_string(str, from, freeok)
char *str;
char *from;
int *freeok;
{
register char *new1, *new2;
register unsigned char *strskip;
register short len;
for (strskip = (UBYTE *)str; *strskip && *strskip != ' ' && *strskip != ';' && *strskip != '|' && *strskip != 0x80; ++strskip);
len = strlen(from);
new1 = malloc((len << 2) + 2);
preformat(from, new1);
len = strlen(new1) + strlen(strskip);
new2 = malloc(len+2);
strcpy(new2, new1);
strcat(new2, strskip);
new2[len+1] = 0;
free (new1);
if (*freeok)
free (str);
*freeok = 1;
return (new2);
}
find_command(str)
register char *str;
{
register short i;
register short len = strlen(str);
register struct COMMAND *cmd;
if (*str >= '0' && *str <= '9')
return (1);
for (i = 0, cmd = Command; cmd->func; ++cmd, ++i) {
if (cmd->stat & ST_EXA) {
if (strcmp(str, cmd->name) == 0)
return((int)i);
} else {
if (strncmp (str, cmd->name, len) == 0)
return ((int)i);
}
}
return (0);
}
do_help()
{
register struct COMMAND *com;
for (com = &Command[2]; com->func; ++com)
fhprintf (Cout, "%s ", com->name);
Oputs ("");
return (0);
}
\Rogue\Monster\
else
echo "will not over write execom.c"
fi
if [ `wc -c execom.c | awk '{printf $1}'` -ne 14743 ]
then
echo `wc -c execom.c | awk '{print "Got " $1 ", Expected " 14743}'`
fi
if `test ! -s fexec1.c`
then
echo "writing fexec1.c"
cat > fexec1.c << '\Rogue\Monster\'
/*
* FEXEC1.C
*
* (C)CopyRight 1987 Matthew Dillon, All rights reserved.
*
* wait() and fexecv()
*
* This code originated from Manx's fexecv code. I claim credit only
* for the major modifications I've done to it.
*/
#include "shell.h"
#include <libraries/dosextens.h>
typedef struct CommandLineInterface CLI;
typedef struct FileHandle FH;
static int ret_val;
wait()
{
return(ret_val);
}
fexecv(cmd, argv, stdin_str, stdout_str, stdout_append)
char *cmd, **argv;
char *stdin_str, *stdout_str;
{
register CLI *cli;
register char **ap, *cp, *arg;
PROC *pp;
APTR sav_ret;
BPTR sav_CIS, sav_COS;
long save_stdin_buf, save_stdin_pos, save_stdin_end;
long len, seg, sav_seg;
long openmode;
long *stk;
FH *fhp, *stdin, *stdout;
char buf[40];
pp = FindTask(0L);
if ((cli = (CLI *)((long)pp->pr_CLI << 2)) == 0)
return(-1);
if ((seg = LoadIt(cmd)) == 0)
return(-3);
stdin = (FH *)((stdin_str)? Open(stdin_str, 1005) : pp->pr_CIS);
if (!stdin) {
fhprintf(Cerr, "Input redirection error\n");
return(-4);
}
openmode = (stdout_append) ? 1005 : 1006;
stdout= (FH *)((stdout_str)? Open(stdout_str, openmode) : pp->pr_COS);
if (!stdout) {
fhprintf(Cerr, "Output redirection error\n");
if (stdin_str)
Close(stdin);
return(-5);
}
if (stdout_append)
Seek(stdout, 0, 1);
sav_seg = cli->cli_Module;
cli->cli_Module = seg;
stk = (long *)AllocMem(4 * cli->cli_DefaultStack + 8, 0);
*stk = 4 * cli->cli_DefaultStack + 8;
stk = (long *)((long)stk + 4 * cli->cli_DefaultStack);
stk[0] = 4 * cli->cli_DefaultStack;
stk[1] = ((long *)pp->pr_ReturnAddr)[1];
sav_ret = pp->pr_ReturnAddr;
pp->pr_ReturnAddr = (APTR)stk;
for (len = 1, ap = argv + 1; *ap; ++ap) /* length of command line */
len += strlen(*ap) + 1;
cp = arg = malloc(len + 1);
for (ap = argv + 1; *ap; ++ap) {
strcpy(cp, *ap);
strcat(cp, " ");
cp += strlen(cp);
}
if (len > 199) /* BCPL parameter limit */
len = 199;
arg[len-1] = '\n'; /* for BCPL */
arg[len] = 0; /* for C */
cp = (char *)((long)cli->cli_CommandName << 2);
movmem(cp, buf, 40);
strcpy(cp + 1, cmd);
cp[0] = strlen(cmd);
fhp = (FH *)((long)stdin << 2);
save_stdin_buf = fhp->fh_Buf;
save_stdin_pos = fhp->fh_Pos;
save_stdin_end = fhp->fh_End;
fhp->fh_Buf = (long)AllocMem(202, 0) >> 2;
bmov(arg, fhp->fh_Buf<<2, len);
fhp->fh_Pos = 0;
fhp->fh_End = len;
sav_CIS = pp->pr_CIS;
sav_COS = pp->pr_COS;
pp->pr_CIS = (BPTR)stdin;
pp->pr_COS = (BPTR)stdout;
/*
* pr_Result2 must be NULL or RUN/NEWCLI think the command line is
* somewhere other than in the file handle. The cli_Interactive
* field gets cleared sometimes (how???), and for some reason, signal
* 31 is set sometimes and might cause inproper operation of RUN.
*/
pp->pr_Result2 = NULL;
cli->cli_Interactive = -1;
SetSignal(0L, 0x80000000);
ret_val = doexec(len, arg, (seg+1)<<2, stk);
FreeMem(fhp->fh_Buf<<2, 202);
fhp->fh_Buf = save_stdin_buf;
fhp->fh_Pos = save_stdin_pos;
fhp->fh_End = save_stdin_end;
if (stdin_str)
Close(stdin);
if (stdout_str)
Close(stdout);
pp->pr_CIS = sav_CIS;
pp->pr_COS = sav_COS;
UnLoadSeg(cli->cli_Module);
pp->pr_ReturnAddr = sav_ret;
cli->cli_Module = sav_seg;
free(arg);
movmem(buf, cp, 40);
return(0);
}
LoadIt(cmd)
char *cmd;
{
long seg;
mountrequest(0);
if ((seg = LoadSeg(cmd)) == NULL) {
register long lock;
char buf[128];
if (lock = FindIt(cmd, "", buf)) {
register long pardir = ParentDir(lock);
if (pardir) {
register long oldir = CurrentDir(pardir);
seg = LoadSeg(cmd);
CurrentDir(oldir);
UnLock(pardir);
}
UnLock(lock);
}
}
mountrequest(1);
return(seg);
}
/*
* Find a specific command (cmd) with extension (ext). Returns
* a lock if found, else NULL. Searches both the symbolic path and
* the CLI path. The symbolic path is searched first.
*/
long
FindIt(cmd, ext, buf)
char *cmd;
char *ext;
char *buf;
{
register long lock = 0;
register char *p;
PROC *myproc = FindTask(0);
strcpy(buf, cmd);
strcat(buf, ext);
if (rindex(buf, ':') || rindex(buf, '/'))
return(Lock(buf, ACCESS_READ));
if ((p = get_var(LEVEL_SET, V_PATH)) == NULL)
p = "";
#ifdef DEBUG
if (SDebug)
printf ("FindIt: try: %s\n", buf);
#endif
while ((lock = Lock(buf, ACCESS_READ)) == 0 || !isfile(lock)) {
register short n;
if (lock)
UnLock(lock);
if (*p == '\0') {
buf[0] = 0;
break;
}
for (n = 0; p[n] && p[n] != ','; ++n);
strncpy(buf, p, n);
buf[n] = 0;
strcat(buf, cmd);
strcat(buf, ext);
p += n + (*p != 0);
#ifdef DEBUG
if (SDebug)
printf ("FindIt: try: %s\n", buf);
#endif
}
#ifdef DEBUG
if (SDebug)
puts ("FindIt 1");
#endif
if (lock)
return(lock);
/*
* Search the CLI path by CurrentDir'ing each lock and
* attempting to lock the name
*/
#ifdef DEBUG
if (SDebug)
puts("SEARCH CLI");
#endif
strcpy(buf, cmd);
strcat(buf, ext);
if (myproc->pr_CLI) {
long oldir;
long dupdir;
register LOCK *dirlock = (LOCK *)(((CLI *)(myproc->pr_CLI << 2))->cli_CommandDir << 2);
for (; dirlock; dirlock = (LOCK *)(dirlock->fl_Link << 2)) {
oldir = CurrentDir(((long *)dirlock)[1]);
lock = Lock(buf, ACCESS_READ);
CurrentDir(oldir);
if (lock)
break;
}
}
#ifdef DEBUG
if (SDebug)
puts("FindIt done");
#endif
return(lock);
}
static
isfile(lock)
long lock;
{
register FIB *fib = (FIB *)malloc(sizeof(FIB));
register int result = 0;
if (fib) {
if (Examine(lock, fib))
result = fib->fib_DirEntryType;
free(fib);
}
return(result < 0); /* is it a file? */
}
\Rogue\Monster\
else
echo "will not over write fexec1.c"
fi
if [ `wc -c fexec1.c | awk '{printf $1}'` -ne 5948 ]
then
echo `wc -c fexec1.c | awk '{print "Got " $1 ", Expected " 5948}'`
fi
if `test ! -s fexec2.asm`
then
echo "writing fexec2.asm"
cat > fexec2.asm << '\Rogue\Monster\'
;FEXEC2.ASM
;
; Again, this code originated from Manx, but has been heavily re-written
;
xdef _doexec
xref _LVOFreeMem
xref _SysRegs
xref _SysBase
xref _savsp
xref _savefp
;
;doexec(len, arg, (seg+1)<<2, stk)
; D0 A0 A4 A7
;
FAR data ;because we totally trash A4 within the
FAR code ;routine.
_doexec:
move.l sp,_savefp ;Save Frame Pointer
movem.l d2-d7/a2-a6,-(sp) ;save Registers
move.l sp,_savsp ;save current SP
lea _SysRegs,A0
movem.l (A0),D0-D7/A0-A6 ;Get System Startup Registers (BCPL stuff)
move.l _savefp,A0 ;A0 = frame pointer
movem.l 4(A0),d0/a0/a4/a7 ;load parameters, including new SP
move.l d0,12(a1) ;set length
move.l a0,d1 ;copy to dreg
lsr.l #2,d1 ;convert to BPTR
move.l d1,8(a1) ;set ptr
jsr (a4) ;call new program
movem.l (sp)+,d2/d3 ;get stk siz and old sp
move.l sp,a1 ;save current sp
move.l _savsp,sp ;get back our sp
move.l d0,-(sp) ;save return code so we don't loose it
sub.l d2,a1 ;Backup from end of stack to start
sub.l #8,a1 ;point over header placed on stack
move.l (a1),d0 ;get size to free
move.l _SysBase,a6 ;get ExecBase
jsr _LVOFreeMem(a6) ;Free memory allocated for stack
move.l (sp)+,d0 ;D0 = return code
movem.l (sp)+,D2-D7/A2-A6 ;restore Registers
rts
\Rogue\Monster\
else
echo "will not over write fexec2.asm"
fi
if [ `wc -c fexec2.asm | awk '{printf $1}'` -ne 1670 ]
then
echo `wc -c fexec2.asm | awk '{print "Got " $1 ", Expected " 1670}'`
fi
if `test ! -s globals.c`
then
echo "writing globals.c"
cat > globals.c << '\Rogue\Monster\'
/*
* GLOBALS.C
*
* (c)1986 Matthew Dillon 9 October 1986
*
*
* Most global variables.
*
*/
#include "shell.h"
struct HIST *H_head, *H_tail; /* HISTORY lists */
struct PERROR Perror[] = { /* error code->string */
103, "insufficient free storage",
105, "task table full",
120, "argument line invalid or too long",
121, "file is not an object module",
122, "invalid resident library during load",
201, "no default directory",
202, "object in use",
203, "object already exists",
204, "directory not found",
205, "object not found",
206, "bad stream name",
207, "object too large",
209, "action not known",
210, "invalid stream component name",
211, "invalid object lock",
212, "object not of required type",
213, "disk not validated",
214, "disk write protected",
215, "rename across devices",
216, "directory not empty",
217, "too many levels",
218, "device not mounted",
219, "seek error",
220, "comment too long",
221, "disk full",
222, "file delete protected",
223, "file write protected",
224, "file read protected",
225, "not a DOS disk",
226, "no disk",
232, "no more entries in directory",
/* custom error messages */
500, "bad arguments",
501, "label not found",
502, "must be within source file",
503, "Syntax Error",
504, "redirection error",
505, "pipe error",
506, "too many arguments",
507, "destination not a directory",
508, "cannot mv a filesystem",
509, "Operation Aborted",
510, "Too many if's",
0, NULL
};
char *av[MAXAV]; /* Internal argument list */
int Src_base[MAXSRC]; /* file pointers for source files */
long Src_pos[MAXSRC]; /* seek position storage for same */
char If_base[MAXIF]; /* If/Else stack for conditionals */
short H_len, H_tail_base; /* History associated stuff */
short H_stack; /* AddHistory disable stack */
short E_stack; /* Exception disable stack */
short Src_stack, If_stack; /* Stack Indexes */
short ac; /* Internal argc */
short SDebug; /* Debug mode */
short SDisable; /* Disable com. execution (conditionals) */
short Verbose; /* Verbose mode for source files */
long Lastresult; /* Last return code */
short Exec_abortline; /* flag to abort rest of line */
short Exec_ignoreresult; /* flag to ignore result */
short Quit; /* Quit flag */
long Cout, Cin, Cerr; /* Current input and output file handles */
long Cout_append; /* append flag for Cout */
long Uniq; /* unique value */
char *Cin_name, *Cout_name;/* redirection input/output name or NULL */
char *Pipe1, *Pipe2; /* the two pipe temp. files */
short S_histlen = 20; /* Max # history entries */
short S_ignoreeof;
long SysRegs[16] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 };
long savsp, savefp;
\Rogue\Monster\
else
echo "will not over write globals.c"
fi
if [ `wc -c globals.c | awk '{printf $1}'` -ne 3086 ]
then
echo `wc -c globals.c | awk '{print "Got " $1 ", Expected " 3086}'`
fi
if `test ! -s hat.c`
then
echo "writing hat.c"
cat > hat.c << '\Rogue\Monster\'
/*
* HAT.C
*
* Modify the last history entry ^search^replace. Called from
* MAIN.C
*
*/
extern char *last_history_entry();
hat_replace(buf)
char *buf;
{
char res[256];
char *ptr, *hb, *repstr, *srchstr;
int searchlen, replacelen;
srchstr = buf + 1;
for (repstr = srchstr; *repstr && *repstr != '^'; ++repstr);
if (*repstr) {
searchlen = repstr - srchstr;
*repstr = '\0';
++repstr;
}
replacelen = strlen(repstr);
for (ptr = hb = last_history_entry(); *ptr; ++ptr) {
if (strncmp(ptr, srchstr, searchlen) == 0) {
bmov(hb, res, ptr - hb); /* first part of history */
res[ptr-hb] = '\0'; /* add 0 */
strcat(res, repstr); /* add replace string */
strcat(res, ptr+searchlen); /* add rest of history */
strcpy(buf, res); /* copy */
puts (buf);
return(1); /* done */
}
}
puts ("modifier failed");
*buf = '\0';
return(0);
}
\Rogue\Monster\
else
echo "will not over write hat.c"
fi
if [ `wc -c hat.c | awk '{printf $1}'` -ne 992 ]
then
echo `wc -c hat.c | awk '{print "Got " $1 ", Expected " 992}'`
fi
if `test ! -s main.c`
then
echo "writing main.c"
cat > main.c << '\Rogue\Monster\'
/*
* MAIN.C
*
* (C)Copyright 1987 Matthew Dillon, All rights reserved
*
* Contains initialization and other stuff. Note that there is no
* support for workbench startup. This isn't simply a matter of
* setting up a window.... to get this baby to work from workbench we
* would need to simulate an entire CLI (proc->pr_CLI must be valid).
*
*/
#include "shell.h"
#include <libraries/dosextens.h>
#include <stdio.h>
extern long SetSignal();
char Inline[256];
static long Orig_dir;
extern int Enable_Abort;
main(argc, argv)
short argc;
register char *argv[];
{
char *prompt;
struct Process *proc;
register short i;
Enable_Abort = 0;
proc = (PROC *)FindTask(0);
if (proc->pr_CLI == NULL) /* sorry, no WB startup */
exit(1000);
Orig_dir = proc->pr_CurrentDir;
CurrentDir(DupLock(Orig_dir));
init_vars();
init();
seterr();
do_cd(NULL, -1);
for (i = 1; i < argc; ++i) {
if (strcmp(argv[i], "-c") == 0) {
Inline[0] = '\0';
for (++i; i < argc; ++i) {
if (*argv[i] == '\"') { /* CLI quotes? */
strcat(Inline, argv[i]+1); /* remove quotes */
Inline[strlen(Inline)-1] = '\0';
} else {
strcat(Inline, argv[i]);
}
if (i + 1 < argc)
strcat(Inline, " ");
}
exec_command(Inline);
main_exit(0);
}
strcpy (Inline, "source ");
strcat (Inline, argv[i]);
av[0] = "source";
av[1] = argv[i];
do_source (Inline, 0);
}
for (;;) {
if ((prompt = get_var (LEVEL_SET, V_PROMPT)) == NULL)
prompt = "echo -n \"% \"";
/*
*
* Removed, WaitForChar() is buggy
*
if (CHECKBREAK()) {
while (WaitForChar(Input(), 10))
gets(Inline);
}
*/
++H_stack;
++Exec_ignoreresult;
exec_command (prompt);
--Exec_ignoreresult;
--H_stack;
if (Quit)
main_exit(0);
if (gets(Inline) == NULL) {
if (IsInteractive(Input()) && !S_ignoreeof)
main_exit(0);
clearerr(stdin);
}
resetbreak();
if (*Inline == '^')
hat_replace(Inline);
if (*Inline)
exec_command(Inline);
}
}
init_vars()
{
if (IsInteractive(Input()))
set_var (LEVEL_SET, V_PROMPT, "echo -n \"% \"");
else
set_var (LEVEL_SET, V_PROMPT, "");
set_var (LEVEL_SET, V_HIST, "20");
set_var (LEVEL_SET, V_PATH, "ram:,ram:c/,c:,df2:c/,df1:c/,df0:c/");
}
init()
{
static char pipe1[32], pipe2[32];
Cin = Input();
Cout= Cerr = Output();
Uniq= (long)pipe1; /* address of some global variable */
Pipe1 = pipe1;
Pipe2 = pipe2;
sprintf (pipe1, "ram:pipe1_%ld", Uniq);
sprintf (pipe2, "ram:pipe2_%ld", Uniq);
}
main_exit(n)
{
UnLock(CurrentDir(Orig_dir));
do_cldres();
exit (n);
}
docheckbreak()
{
if (checkbreak()) {
printf("^C\n");
return(1);
}
return(0);
}
\Rogue\Monster\
else
echo "will not over write main.c"
fi
if [ `wc -c main.c | awk '{printf $1}'` -ne 2786 ]
then
echo `wc -c main.c | awk '{print "Got " $1 ", Expected " 2786}'`
fi
if `test ! -s run.c`
then
echo "writing run.c"
cat > run.c << '\Rogue\Monster\'
/*
* RUN.C
*
* (C)CopyRight 1987 Matthew Dillon, All rights reserved.
*
* RUN handles running of external commands.
*
*/
#include "shell.h"
#include "libraries/dos.h"
extern long *SysRegs;
extern struct FileLock *Clock;
do_run(str)
char *str;
{
int i;
#ifdef DEBUG
if (SDebug) {
printf ("RUN: %s '>%s' '<%s' '>>%ld'\n", av[0], (Cin_name)?Cin_name:"&", (Cout_name)?Cout_name:"&", Cout_append);
printf ("av[0]=%08lx [1]=%08lx [2]=%08lx\n", av[0],av[1], av[2]);
}
#endif
if (fexecv(av[0], av, Cin_name, Cout_name, Cout_append) >= 0) {
i = wait();
} else {
register long lock;
register char *copy;
char buf[128];
mountrequest(0);
lock = FindIt(av[0], ".sh", buf);
mountrequest(1);
#ifdef DEBUG
if (SDebug)
puts("do_run: 1");
#endif
if (lock == NULL) {
perror(av[0]); /* fixed 26 Mar 88 */
return (-1);
}
av[0] = (char *)-1;
av[1] = (char *)lock;
copy = malloc(strlen(str)+3);
strcpy(copy+2,str);
copy[0] = 'x';
copy[1] = ' ';
#ifdef DEBUG
if (SDebug)
printf ("Do_source: %s\n", copy);
#endif
i = do_source(copy);
free(copy);
}
if (Clock != (struct FileLock *)((struct Process *)FindTask(NULL))->pr_CurrentDir) {
Clock = (struct FileLock *)((struct Process *)FindTask(NULL))->pr_CurrentDir;
puts("Warning: Current Directory has changed");
}
return (i);
}
\Rogue\Monster\
else
echo "will not over write run.c"
fi
if [ `wc -c run.c | awk '{printf $1}'` -ne 1353 ]
then
echo `wc -c run.c | awk '{print "Got " $1 ", Expected " 1353}'`
fi
if `test ! -s set.c`
then
echo "writing set.c"
cat > set.c << '\Rogue\Monster\'
/*
* SET.C
*
* (c)1986 Matthew Dillon 9 October 1986
*
* Handles the variable lists for normal variables, aliases, and labels.
*/
#include "shell.h"
#define MAXLEVELS (3 + MAXSRC)
struct MASTER {
struct MASTER *next;
struct MASTER *last;
char *name;
char *text;
};
static struct MASTER *Mbase[MAXLEVELS];
char *
set_var(level, name, str)
short level;
register char *name, *str;
{
register struct MASTER *base = Mbase[level];
register struct MASTER *last;
register short len;
for (len = 0; isalphanum(name[len]); ++len);
while (base != NULL) {
if (strlen(base->name) == len && strncmp (name, base->name, len) == 0) {
Free (base->text);
goto gotit;
}
last = base;
base = base->next;
}
if (base == Mbase[level]) {
base = Mbase[level] = (struct MASTER *)malloc(sizeof(struct MASTER));
base->last = NULL;
} else {
base = (struct MASTER *)malloc (sizeof(struct MASTER));
base->last = last;
last->next = base;
}
base->name = malloc (len + 1);
bmov (name, base->name, len);
base->name[len] = 0;
base->next = NULL;
gotit:
base->text = malloc (strlen(str) + 1);
strcpy (base->text, str);
return (base->text);
}
char *
get_var (level, name)
short level;
register char *name;
{
register struct MASTER *base = Mbase[level];
register unsigned char *scr;
register short len;
static char *EnvBuf = NULL;
char buf[128];
long fh;
for (scr = (UBYTE *)name; *scr && *scr != 0x80 && *scr != ' ' && *scr != ';' && *scr != '|'; ++scr);
len = scr - name;
while (base != NULL) {
if (strlen(base->name) == len && strncmp (name, base->name, len) == 0)
return (base->text);
base = base->next;
}
mountrequest(0);
strcpy(buf, "ENV:");
strncat(buf, name, len);
buf[4+len] = 0;
if (fh = Open(buf, 1005)) {
long len = (Seek(fh, 0L, 1), Seek(fh, 0L, 0));
if (len < 0)
len = 256;
if (EnvBuf)
free(EnvBuf);
if (EnvBuf = malloc(len+1)) {
Seek(fh, 0L, -1);
len = Read(fh, EnvBuf, len);
if (len < 0)
len = 0;
EnvBuf[len] = 0;
}
Close(fh);
mountrequest(1);
return(EnvBuf);
}
mountrequest(1);
return (NULL);
}
unset_level(level)
short level;
{
register struct MASTER *base = Mbase[level];
register struct MASTER *next;
while (base) {
next = base->next;
Free (base->name);
Free (base->text);
Free (base);
base = next;
}
Mbase[level] = NULL;
}
unset_var(level, name)
short level;
char *name;
{
register struct MASTER *base = Mbase[level];
register struct MASTER *last = NULL;
register short len;
for (len = 0; isalphanum(name[len]); ++len);
while (base) {
if (strlen(base->name) == len && strncmp (name, base->name, len) == 0) {
if (base != Mbase[level])
last->next = base->next;
else
Mbase[level] = base->next;
if (base->next != NULL)
base->next->last = last;
if (base == Mbase[level])
Mbase[level] = base->next;
Free (base->name);
Free (base->text);
Free (base);
return (1);
}
last = base;
base = base->next;
}
return (-1);
}
do_unset_var(garbage, level)
short level;
char *garbage;
{
register short i;
register char uu = 0;
for (i = 1; i < ac; ++i) {
unset_var (level, av[i]);
if (*av[i] == '_')
uu = '_';
}
update_under(uu);
return (0);
}
do_set_var(command, level)
short level;
char *command;
{
register struct MASTER *base = Mbase[level];
register char *str;
if (ac == 1) {
while (base) {
fhprintf (Cout, "%-10s ", base->name);
Oputs (base->text);
base = base->next;
}
return (0);
}
if (ac == 2) {
str = get_var (level, av[1]);
if (str) {
fhprintf (Cout, "%-10s ", av[1]);
Oputs(str);
} else {
set_var (level, av[1], "");
}
}
if (ac > 2)
set_var (level, av[1], next_word (next_word (command)));
update_under(*av[1]);
return (0);
}
static
update_under(c)
{
register char *str;
if (c == '_') {
S_histlen = (str = get_var(LEVEL_SET, V_HIST)) ? atoi(str) : 0;
S_ignoreeof=(str = get_var(LEVEL_SET, V_IGNOREEOF)) ? 1 : 0;
SDebug = (str = get_var(LEVEL_SET, V_DEBUG)) ? atoi(str) : 0;
Verbose = (get_var(LEVEL_SET, V_VERBOSE)) ? 1 : 0;
if (S_histlen < 2)
S_histlen = 2;
}
}
\Rogue\Monster\
else
echo "will not over write set.c"
fi
if [ `wc -c set.c | awk '{printf $1}'` -ne 4323 ]
then
echo `wc -c set.c | awk '{print "Got " $1 ", Expected " 4323}'`
fi
if `test ! -s shell.h`
then
echo "writing shell.h"
cat > shell.h << '\Rogue\Monster\'
/*
* SHELL.H
*
* (c)1986-1988 Matthew Dillon 18 August 1988
*
*
* SHELL include file.. contains shell parameters and extern's
*
*
*/
#include <local/typedefs.h>
/*#define FIBF_ARCHIVE (1<<4)*/
#define MAXAV 128 /* Max. # arguments */
#define MAXSRC 5 /* Max. # of source file levels */
#define MAXIF 10 /* Max. # of if levels */
#define MAXALIAS 20 /* Max. # of alias levels */
#define LEVEL_SET 0 /* which variable list to use */
#define LEVEL_ALIAS 1
#define LEVEL_LABEL 2
#define V_PROMPT "_prompt" /* your prompt (ascii command) */
#define V_HIST "_history" /* set history depth (value) */
#define V_HISTNUM "_histnum" /* set history numbering var */
#define V_DEBUG "_debug" /* set debug mode */
#define V_VERBOSE "_verbose" /* set verbose for source files */
#define V_STAT "_maxerr" /* worst return value to date */
#define V_LASTERR "_lasterr" /* return value from last comm. */
#define V_CWD "_cwd" /* current directory */
#define V_EXCEPT "_except" /* "nnn;command" */
#define V_PASSED "_passed" /* passed arguments to source fle*/
#define V_PATH "_path" /* path prefix,prefix,prefix.. */
#define V_IGNOREEOF "_ignoreeof" /* ignore EOF for interactive tty*/
#define V_COPYSILENT "_copysilent" /* silent copy */
#define V_COPYDATE "_copydate" /* transport datestamp */
/* EXECOM.C defines */
#define FL_DOLLAR 0x01 /* One of the following */
#define FL_BANG 0x02
#define FL_PERCENT 0x04
#define FL_QUOTE 0x08
#define FL_IDOLLAR 0x10 /* Any or all of the following may be set */
#define FL_EOC 0x20
#define FL_EOL 0x40
#define FL_OVERIDE 0x80
#define FL_WILD 0x100
#define FL_MASK (FL_DOLLAR|FL_BANG|FL_PERCENT|FL_QUOTE)
#define VERSION "V2.10 (C)Copyright 1986-88 Matthew Dillon, All Rights Reserved, 18 August 1988"
#ifndef NULL
#define NULL 0L
#endif
#define CHECKBREAK() docheckbreak()
struct HIST {
struct HIST *next, *prev; /* doubly linked list */
char *line; /* line in history */
};
struct PERROR {
short errnum; /* Format of global error lookup */
char *errstr;
};
struct DPTR { /* Format of directory fetch pointer */
struct FileLock *lock; /* lock on directory */
struct FileInfoBlock *fib; /* mod'd fib for entry */
};
extern struct HIST *H_head, *H_tail;
extern struct PERROR Perror[];
extern struct DPTR *dopen();
extern char *set_var(), *get_var(), *next_word();
extern char *get_history(), *compile_av();
extern char *strcpy(), *strcat(), *gets(), *Ogets();
extern char **expand();
extern long FindIt();
extern char *av[];
extern char *Current;
extern short H_len, H_tail_base, H_stack;
extern short E_stack;
extern short Src_stack, If_stack;
extern short ac;
extern short SDebug, Verbose, SDisable, Quit;
extern long Lastresult;
extern short Exec_abortline, Exec_ignoreresult;
extern short S_histlen, S_ignoreeof;
extern long Uniq;
extern long Cin, Cout, Cerr, Cout_append;
extern char *Cin_name, *Cout_name;
extern char Cin_type, Cout_type; /* these variables are in transition */
extern char *Pipe1, *Pipe2;
extern long DResBase;
extern int Src_base[MAXSRC];
extern long Src_pos[MAXSRC];
extern char If_base[MAXIF];
\Rogue\Monster\
else
echo "will not over write shell.h"
fi
if [ `wc -c shell.h | awk '{printf $1}'` -ne 3410 ]
then
echo `wc -c shell.h | awk '{print "Got " $1 ", Expected " 3410}'`
fi
if `test ! -s sort.c`
then
echo "writing sort.c"
cat > sort.c << '\Rogue\Monster\'
/*
* SORT.C
*
* a QuickSort is used for speed, simplicity, and small code size.
*
*/
extern short QSplit();
QuickSort(av, n)
char *av[];
short n;
{
short b;
if (n > 0) {
b = QSplit(av, n);
QuickSort(av, b);
QuickSort(av+b+1, n - b - 1);
}
}
/*
* QSplit called as a second routine so I don't waste stack on QuickSort's
* recursivness.
*/
short
QSplit(av, n)
register char *av[];
short n;
{
register short i, b;
register char *element, *scr;
element = av[0];
for (b = 0, i = 1; i < n; ++i) {
if (strcmp(av[i], element) < 0) {
++b;
scr = av[i]; av[i] = av[b]; av[b] = scr;
}
}
scr = av[0]; av[0] = av[b]; av[b] = scr;
return (b);
}
\Rogue\Monster\
else
echo "will not over write sort.c"
fi
if [ `wc -c sort.c | awk '{printf $1}'` -ne 705 ]
then
echo `wc -c sort.c | awk '{print "Got " $1 ", Expected " 705}'`
fi
if `test ! -s sub.c`
then
echo "writing sub.c"
cat > sub.c << '\Rogue\Monster\'
/*
* SUB.C
*
* (C)Copyright 1987 Matthew Dillon, All rights reserved
*
* Subroutines used throughout the shell (not very descriptive, am I?)
*/
#include <exec/types.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include "shell.h"
#define HM_STR 0 /* various HISTORY retrieval modes */
#define HM_REL 1
#define HM_ABS 2
extern struct FileLock *Lock(), *DupLock(), *CurrentDir();
extern struct FileLock *Clock;
seterr()
{
char buf[32];
int stat;
sprintf(buf, "%ld", Lastresult);
set_var(LEVEL_SET, V_LASTERR, buf);
stat = atoi(get_var(LEVEL_SET, V_STAT));
if (stat < Lastresult)
stat = Lastresult;
sprintf(buf, "%ld", stat);
set_var(LEVEL_SET, V_STAT, buf);
}
char *
next_word(str)
register char *str;
{
while (*str && *str != ' ' && *str != 9)
++str;
while (*str && (*str == ' ' || *str == 9))
++str;
return (str);
}
char *
compile_av(av, start, end)
short start, end;
char **av;
{
char *cstr;
short i, len;
len = 0;
for (i = start; i < end; ++i)
len += strlen(av[i]) + 1;
cstr = malloc(len + 1);
*cstr = '\0';
for (i = start; i < end; ++i) {
strcat (cstr, av[i]);
strcat (cstr, " ");
}
return (cstr);
}
/*
* FREE(ptr) --frees without actually freeing, so the data is still good
* immediately after the free.
*/
Free(ptr)
char *ptr;
{
static char *old_ptr;
if (old_ptr)
free (old_ptr);
old_ptr = ptr;
}
/*
* Add new string to history (H_head, H_tail, H_len,
* S_histlen
*/
add_history(str)
char *str;
{
register struct HIST *hist;
while (H_len > S_histlen)
del_history();
hist = (struct HIST *)malloc (sizeof(struct HIST));
if (H_head == NULL) {
H_head = H_tail = hist;
hist->next = NULL;
} else {
hist->next = H_head;
H_head->prev = hist;
H_head = hist;
}
hist->prev = NULL;
hist->line = malloc (strlen(str) + 1);
strcpy (hist->line, str);
++H_len;
}
del_history()
{
if (H_tail) {
--H_len;
++H_tail_base;
free (H_tail->line);
if (H_tail->prev) {
H_tail = H_tail->prev;
free (H_tail->next);
H_tail->next = NULL;
} else {
free (H_tail);
H_tail = H_head = NULL;
}
}
}
char *
last_history_entry()
{
if (H_head)
return(H_head->line);
return("");
}
char *
get_history(ptr)
char *ptr;
{
register struct HIST *hist;
register short len;
short mode = HM_REL;
long num = 1;
char *str;
char *result = NULL;
if (ptr[1] >= '0' && ptr[1] <= '9') {
mode = HM_ABS;
num = atoi(&ptr[1]);
goto skip;
}
switch (ptr[1]) {
case '!':
break;
case '-':
num += atoi(&ptr[2]);
break;
default:
mode = HM_STR;
str = ptr + 1;
break;
}
skip:
switch (mode) {
case HM_STR:
len = strlen(str);
for (hist = H_head; hist; hist = hist->next) {
if (strncmp(hist->line, str, len) == 0 && *hist->line != '!') {
result = hist->line;
break;
}
}
break;
case HM_REL:
for (hist = H_head; hist && num--; hist = hist->next);
if (hist)
result = hist->line;
break;
case HM_ABS:
len = H_tail_base;
for (hist = H_tail; hist && len != num; hist = hist->prev, ++len);
if (hist)
result = hist->line;
break;
}
if (result) {
Eputs (result);
return(result);
}
Eputs ("History substitution failed");
return ("");
}
replace_head(str)
char *str;
{
if (str == NULL)
str = "";
if (H_head) {
free (H_head->line);
H_head->line = malloc (strlen(str)+1);
strcpy (H_head->line, str);
}
}
perror(str)
char *str;
{
ierror(str, IoErr());
}
ierror(str, err)
register char *str;
short err;
{
register struct PERROR *per = Perror;
if (err) {
for (; per->errstr; ++per) {
if (per->errnum == err) {
fhprintf (Cerr, "%s%s%s\n",
per->errstr,
(str) ? ": " : "",
(str) ? str : ""
);
return(err);
}
}
fhprintf (Cerr, "Unknown DOS error %ld %s\n", err, (str) ? str : "");
}
return (err);
}
/*
* Disk directory routines
*
* dptr = dopen(name, stat)
* struct DPTR *dptr;
* char *name;
* int *stat;
*
* dnext(dptr, name, stat)
* struct DPTR *dptr;
* char **name;
* int *stat;
*
* dclose(dptr) -may be called with NULL without harm
*
* dopen() returns a struct DPTR, or NULL if the given file does not
* exist. stat will be set to 1 if the file is a directory. If the
* name is "", then the current directory is openned.
*
* dnext() returns 1 until there are no more entries. The **name and
* *stat are set. *stat = 1 if the file is a directory.
*
* dclose() closes a directory channel.
*
*/
struct DPTR *
dopen(name, stat)
char *name;
register int *stat;
{
register struct DPTR *dp;
*stat = 0;
dp = (struct DPTR *)malloc(sizeof(struct DPTR));
if (*name == '\0')
dp->lock = DupLock (Clock);
else
dp->lock = Lock (name, ACCESS_READ);
if (dp->lock == NULL) {
free (dp);
return (NULL);
}
dp->fib = (struct FileInfoBlock *)
AllocMem(sizeof(struct FileInfoBlock), MEMF_PUBLIC);
if (!Examine (dp->lock, dp->fib)) {
perror (name);
dclose (dp);
return (NULL);
}
if (dp->fib->fib_DirEntryType >= 0)
*stat = 1;
return (dp);
}
dnext(dp, pname, stat)
register struct DPTR *dp;
char **pname;
int *stat;
{
if (dp == NULL)
return (0);
if (ExNext (dp->lock, dp->fib)) {
*stat = (dp->fib->fib_DirEntryType < 0) ? 0 : 1;
*pname = dp->fib->fib_FileName;
return (1);
}
return (0);
}
dclose(dp)
register struct DPTR *dp;
{
if (dp == NULL)
return (1);
if (dp->fib)
FreeMem (dp->fib, sizeof(*dp->fib));
if (dp->lock)
UnLock (dp->lock);
free (dp);
return (1);
}
isdir(file)
char *file;
{
register struct DPTR *dp;
int stat;
stat = 0;
if (dp = dopen (file, &stat))
dclose(dp);
return (stat == 1);
}
free_expand(av)
register char **av;
{
register char **base = av;
if (av) {
while (*av) {
free (*av);
++av;
}
free (base);
}
}
/*
* EXPAND(wild_name, pac)
* wild_name - char * (example: "df0:*.c")
* pac - int * will be set to # of arguments.
*
* Standalone, except in requires Clock to point to the Current-Directory
* lock.
*/
char **
expand(base, pac)
char *base;
int *pac;
{
register char *ptr;
char **eav = (char **)malloc (sizeof(char *));
short eleft, eac;
char *name;
char *bname, *ename, *tail;
int stat, scr;
register struct DPTR *dp;
*pac = eleft = eac = 0;
base = strcpy(malloc(strlen(base)+1), base);
for (ptr = base; *ptr && *ptr != '?' && *ptr != '*'; ++ptr);
for (; ptr >= base && !(*ptr == '/' || *ptr == ':'); --ptr);
if (ptr < base) {
bname = strcpy (malloc(1), "");
} else {
scr = ptr[1];
ptr[1] = '\0';
bname = strcpy (malloc(strlen(base)+1), base);
ptr[1] = scr;
}
ename = ptr + 1;
for (ptr = ename; *ptr && *ptr != '/'; ++ptr);
scr = *ptr;
*ptr = '\0';
tail = (scr) ? ptr + 1 : NULL;
if ((dp = dopen (bname, &stat)) == NULL || stat == 0) {
free (bname);
free (base);
free (eav);
Eputs ("Could not open directory");
return (NULL);
}
while (dnext (dp, &name, &stat)) {
if (compare_ok(ename, name)) {
if (tail) {
int alt_ac;
char *search, **alt_av, **scrav;
struct FileLock *lock;
if (!stat) /* expect more dirs, but this not a dir */
continue;
lock = CurrentDir (Clock = dp->lock);
search = malloc(strlen(name)+strlen(tail)+2);
strcpy (search, name);
strcat (search, "/");
strcat (search, tail);
scrav = alt_av = expand (search, &alt_ac);
CurrentDir (Clock = lock);
if (scrav) {
while (*scrav) {
if (eleft < 2) {
char **scrav = (char **)malloc(sizeof(char *) * (eac + 10));
bmov (eav, scrav, (eac + 1) << 2);
free (eav);
eav = scrav;
eleft = 10;
}
eav[eac] = malloc(strlen(bname)+strlen(*scrav)+1);
strcpy(eav[eac], bname);
strcat(eav[eac], *scrav);
free (*scrav);
++scrav;
--eleft, ++eac;
}
free (alt_av);
}
} else {
if (eleft < 2) {
char **scrav = (char **)malloc(sizeof(char *) * (eac + 10));
bmov (eav, scrav, (eac + 1) << 2);
free (eav);
eav = scrav;
eleft = 10;
}
eav[eac] = malloc (strlen(bname)+strlen(name)+1);
eav[eac] = strcpy(eav[eac], bname);
strcat(eav[eac], name);
--eleft, ++eac;
}
}
}
dclose (dp);
*pac = eac;
eav[eac] = NULL;
free (bname);
free (base);
if (eac)
return (eav);
free (eav);
return (NULL);
}
/*
* Compare a wild card name with a normal name
*/
#define MAXB 8
compare_ok(wild, name)
char *wild, *name;
{
register char *w = wild;
register char *n = name;
char *back[MAXB][2];
register char s1, s2;
register short bi = 0;
while (*n || *w) {
switch (*w) {
case '*':
if (bi == MAXB) {
Eputs ("Too many levels of '*'");
return (0);
}
back[bi][0] = w;
back[bi][1] = n;
++bi;
++w;
continue;
goback:
--bi;
while (bi >= 0 && *back[bi][1] == '\0')
--bi;
if (bi < 0)
return (0);
w = back[bi][0] + 1;
n = ++back[bi][1];
++bi;
continue;
case '?':
if (!*n) {
if (bi)
goto goback;
return (0);
}
break;
default:
s1 = (*n >= 'A' && *n <= 'Z') ? *n - 'A' + 'a' : *n;
s2 = (*w >= 'A' && *w <= 'Z') ? *w - 'A' + 'a' : *w;
if (s1 != s2) {
if (bi)
goto goback;
return (0);
}
break;
}
if (*n) ++n;
if (*w) ++w;
}
return (1);
}
Oputs(str)
char *str;
{
Write (Cout, str, strlen(str));
Write (Cout, "\n", 1);
}
Eputs(str)
char *str;
{
Write (Cerr, str, strlen(str));
Write (Cerr, "\n", 1);
}
char *
Ogets(str)
char *str;
{
register int i = 0;
while (Read(Cin, str + i, 1) == 1) {
if (str[i] == '\n') {
str[i] = 0;
return (str);
}
if (++i == 255) {
str[i] = 0;
return (str);
}
}
return (NULL);
}
\Rogue\Monster\
else
echo "will not over write sub.c"
fi
if [ `wc -c sub.c | awk '{printf $1}'` -ne 11900 ]
then
echo `wc -c sub.c | awk '{print "Got " $1 ", Expected " 11900}'`
fi
if `test ! -s tags`
then
echo "writing tags"
cat > tags << '\Rogue\Monster\'
do_sleep comm1.c /^do_sleep(
do_number comm1.c /^do_number(
do_cat comm1.c /^do_cat(
do_comment comm1.c /^do_comment(
do_dir comm1.c /^do_dir(
disp_entry comm1.c /^disp_entry(
do_quit comm1.c /^do_quit(
do_echo comm1.c /^do_echo(
do_source comm1.c /^do_source(
do_cd comm1.c /^do_cd(
attempt_cd comm1.c /^attempt_cd(
rmlast comm1.c /^rmlast(
do_mkdir comm1.c /^do_mkdir(
do_mv comm1.c /^do_mv(
do_rm comm1.c /^do_rm(
rmdir comm1.c /^rmdir(
do_history comm1.c /^do_history(
do_mem comm1.c /^do_mem(
do_foreach comm1.c /^do_foreach(
do_forever comm1.c /^do_forever(
do_abortline comm2.c /^do_abortline(
do_return comm2.c /^do_return(
do_strhead comm2.c /^do_strhead(
do_strtail comm2.c /^do_strtail(
do_if comm2.c /^do_if(
do_label comm2.c /^do_label(
do_goto comm2.c /^do_goto(
do_inc comm2.c /^do_inc(
do_input comm2.c /^do_input(
do_ver comm2.c /^do_ver(
do_cp comm2.c /^do_cp(
copydir comm2.c /^copydir(
copyfile comm2.c /^copyfile(
do_shellstat comm2.c /^do_shellstat(
do_printenv comm2.c /^do_printenv(
do_setenv comm2.c /^do_setenv(
do_unsetenv comm2.c /^do_unsetenv(
exec_command execom.c /^exec_command(
isalphanum execom.c /^isalphanum(
preformat execom.c /^preformat(
fcomm execom.c /^fcomm(
exarg execom.c /^exarg(
mpush_base execom.c /^mpush_base(
mpush execom.c /^mpush(
mpop_tobase execom.c /^mpop_tobase(
format_insert_string execom.c /^format_insert_string(
find_command execom.c /^find_command(
do_help execom.c /^do_help(
wait fexec1.c /^wait(
fexecv fexec1.c /^fexecv(
LoadIt fexec1.c /^LoadIt(
FindIt fexec1.c /^FindIt(
isfile fexec1.c /^isfile(
hat_replace hat.c /^hat_replace(
main main.c /^main(
init_vars main.c /^init_vars(
init main.c /^init(
main_exit main.c /^main_exit(
docheckbreak main.c /^docheckbreak(
do_run run.c /^do_run(
set_var set.c /^set_var(
get_var set.c /^get_var (
unset_level set.c /^unset_level(
unset_var set.c /^unset_var(
do_unset_var set.c /^do_unset_var(
do_set_var set.c /^do_set_var(
update_under set.c /^update_under(
QuickSort sort.c /^QuickSort(
QSplit sort.c /^QSplit(
seterr sub.c /^seterr(
next_word sub.c /^next_word(
compile_av sub.c /^compile_av(
Free sub.c /^Free(
add_history sub.c /^add_history(
del_history sub.c /^del_history(
last_history_entry sub.c /^last_history_entry(
get_history sub.c /^get_history(
replace_head sub.c /^replace_head(
perror sub.c /^perror(
ierror sub.c /^ierror(
dopen sub.c /^dopen(
dnext sub.c /^dnext(
dclose sub.c /^dclose(
isdir sub.c /^isdir(
free_expand sub.c /^free_expand(
expand sub.c /^expand(
compare_ok sub.c /^compare_ok(
Oputs sub.c /^Oputs(
Eputs sub.c /^Eputs(
Ogets sub.c /^Ogets(
\Rogue\Monster\
else
echo "will not over write tags"
fi
if [ `wc -c tags | awk '{printf $1}'` -ne 2590 ]
then
echo `wc -c tags | awk '{print "Got " $1 ", Expected " 2590}'`
fi
echo "Finished archive 1 of 2"
# if you want to concatenate archives, remove anything after this line
exit
--
Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page
Have five nice days.